package com.example.nonggo.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.BounceInterpolator;
import android.view.animation.Interpolator;

import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class WaveformView extends View {

    private final int MIN_VOICE_SIZE = 20;
    private Paint linePaint;
    private Paint bgPaint;
    private Paint txtPaint;

    List<DrawLine> drawLines = new ArrayList<>();
    private final int LINE_WIDTH = 3; //音量条的宽度
    private final int LINE_SPACE = 10;

    private final int DURATION = 400;
    private Interpolator mInterpolator = new BounceInterpolator();

    private final float initWidthRotas = 0.42f;//最开始显示的宽度占控件整个宽度的比例
    private final float maxWidthRotas = 0.8f;//最大显示宽度
    private float widthRotas = initWidthRotas;//当前显示的宽度

    private int bgRound = 15;//背景圆角的大小,单位dp
    private int showWidth = 0;//显示的宽度
    private Rect textRect = new Rect();
    private volatile boolean quit = false;
    private final String cancelBgColor = "#F85050";
    private final String normalBgColor = "#EFEFEF";
    // 计数器和阈值
    private int countBelowThreshold = 0;
    // 连续12次voiceSize <= 20触发完毕事件，每次250ms，即3秒->改为10s
    private final int THRESHOLD_COUNT = 40;
    private onFinishListener onFinishListener;

    private ValueAnimator animator;

    public WaveformView(Context context) {
        super(context);
    }

    public WaveformView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        linePaint = new Paint();
        linePaint.setColor(Color.WHITE);
        linePaint.setStyle(Paint.Style.FILL);
        linePaint.setStrokeCap(Paint.Cap.ROUND);
        linePaint.setStrokeJoin(Paint.Join.ROUND);

        bgPaint = new Paint();
        bgPaint.setColor(Color.parseColor(normalBgColor));
        bgPaint.setStyle(Paint.Style.FILL);
        bgPaint.setStrokeCap(Paint.Cap.ROUND);
        bgPaint.setStrokeJoin(Paint.Join.ROUND);
        bgPaint.setAntiAlias(true);
        bgRound = dip2px(context, bgRound);

        txtPaint = new Paint();
        txtPaint.setColor(Color.BLACK);
        txtPaint.setStyle(Paint.Style.FILL);
        txtPaint.setStrokeCap(Paint.Cap.ROUND);
        txtPaint.setStrokeJoin(Paint.Join.ROUND);
        txtPaint.setTextSize(dip2px(context, 14));
        txtPaint.setAntiAlias(true);

        buildDrawLines();
        startAnimation();
    }

    private static class DrawLine {
        RectF rectF;
        int maxSize;
        int lineSize;
        boolean small = true;//是否缩小模式，
        float rotas = 1.0f;
        float timeCompletion = 0;//时间完成度，返回在0-1
        int duration = 0;
    }

    public void setCancel(boolean cancel) {
        if (cancel) {
            bgPaint.setColor(Color.parseColor(cancelBgColor));
        } else {
            bgPaint.setColor(Color.parseColor(normalBgColor));
        }
    }

    /**
     * 每条音频线能显示的最大值与showVoiceSize的比值
     */
    float[] ratios = new float[]{0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.5f, 0.3f, 0.5f, 0.8f, 1.0f, 0.8f, 0.5f, 0.3f, 0.5f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f, 0.2f};

    private void buildDrawLines() {
        drawLines.clear();
        for (float ratio : ratios) {
            int maxSize = (int) (MIN_VOICE_SIZE * ratio);
            RectF rect = new RectF(-LINE_WIDTH / 2, -maxSize / 2, LINE_WIDTH / 2, maxSize / 2);
            DrawLine drawLine = new DrawLine();
            drawLine.maxSize = maxSize;
            drawLine.rectF = rect;
            drawLine.lineSize = new Random().nextInt(maxSize);
            drawLine.rotas = ratio;
            //通过设置不同的时间完成度，让每个音量条有不同的初始值。可以实现参差不齐的效果
            // drawLine.timeCompletion = ratio;
            drawLine.duration = (int) (DURATION * (1.0f / ratio));
            drawLines.add(drawLine);
        }
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    private static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    private boolean showText = false;
    private String content = null;

    public void setContent(String content) {
        showText = true;
        this.content = content;
        txtPaint.getTextBounds(content, 0, content.length(), textRect);
    }

    private boolean toBig = true;

    /**
     * 设置音量大小，其实就是音量条显示的高度（单位像素)
     *
     * @param voiceSize
     */
    public void addVoiceSize(int voiceSize) {
        // showVoiceSize = Math.max(MIN_VOICE_SIZE, voiceSize);
        if (toBig) {
            //开始变大
            widthRotas = initWidthRotas;
            showWidth = (int) (getWidth() * widthRotas);
            invalidate();
            toBig = false;
        }

        for (DrawLine drawLine : drawLines) {
            drawLine.timeCompletion = 0;
            drawLine.small = false;
            drawLine.maxSize = (int) (drawLine.rotas * voiceSize);
        }
        invalidate();
        // 更新计数器
        if (voiceSize <= MIN_VOICE_SIZE) {
            countBelowThreshold++;
            if (countBelowThreshold >= THRESHOLD_COUNT) {
                // 触发完毕事件
                if (onFinishListener != null) {
                    Log.e("startRecording", "onCreate: setOnFinishListener 语音输入完毕");
                    onFinishListener.onFinish();
                }
                countBelowThreshold = 0; // 重置计数器
            }
        } else {
            countBelowThreshold = 0; // 重置计数器
        }
    }

    public void setOnFinishListener(WaveformView.onFinishListener onFinishListener) {
        this.countBelowThreshold = 0;
        this.onFinishListener = onFinishListener;
    }

    public void setInterpolator(Interpolator mInterpolator) {
        this.mInterpolator = mInterpolator;
    }

    private int showVoiceSize = 40;

    private static final int[] checkModeItemSize = new int[]{15, 20, 25, 30, 25, 20, 15};
    private int checkStarIndex = 0;
    private boolean isCheckMode = false;

    private void startAnimation() {
        animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(DURATION);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setInterpolator(mInterpolator);
        animator.addUpdateListener(animation -> {
            float animatedValue = (float) animation.getAnimatedValue();
            for (DrawLine drawLine : drawLines) {
                float animationCompletion = mInterpolator.getInterpolation(animatedValue);
                int lineSize = 0;
                if (drawLine.small) {
                    //变小
                    lineSize = (int) ((1 - animationCompletion) * drawLine.maxSize);
                } else {
                    lineSize = (int) (animationCompletion * drawLine.maxSize);
                }
                if (animatedValue >= 1) {
                    //完成了单边的缩小，或增长，则切换模式
                    drawLine.small = !drawLine.small;
                }
                lineSize = Math.max(lineSize, 10);//对最小值进行过滤
                RectF rectF = drawLine.rectF;
                rectF.top = -lineSize * 1.0f / 2;
                rectF.bottom = lineSize * 1.0f / 2;
                drawLine.lineSize = lineSize;
            }
            invalidate();
        });
        animator.start();
    }

    public void onDestroy() {
        if (animator != null) {
            animator.cancel();
            animator = null;
        }
        quit = true;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        showWidth = (int) (widthRotas * w);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);
        //画背景
        // canvas.drawRoundRect(-showWidth / 2, -getHeight() / 2, showWidth / 2, getHeight() / 2, bgRound, bgRound, bgPaint);
        if (showText) {
            int txtHeight = textRect.height() / 2;
            int txtWidth = textRect.width() / 2;
            canvas.drawText(content, -txtWidth, txtHeight, txtPaint);
        } else {
            float offsetX = (drawLines.size() - 1) * 1.0f / 2 * (LINE_WIDTH + LINE_SPACE);
            canvas.translate(-offsetX, 0);
            for (DrawLine drawLine : drawLines) {
                canvas.drawRoundRect(drawLine.rectF, 5, 5, linePaint);
                canvas.translate(LINE_WIDTH + LINE_SPACE, 0);
            }
        }
        canvas.restore();
    }

    public interface onFinishListener {
        void onFinish();
    }
}
